﻿namespace RPGTest.Framework.FSM
{
    using System;
    using System.Collections.Generic;
    using UnityEngine;

    /// <summary>
    /// 有限状态机
    /// </summary>
    public class FiniteStateMachine
    {
        #region 属性
        /// <summary>
        /// 当前状态
        /// </summary>
        public Type CurrentState { get; private set; }

        /// <summary>
        /// 是否启用状态机
        /// </summary>
        bool enable;

        /// <summary>
        /// 状态列表
        /// </summary>
        Dictionary<Type, FiniteState> _fsmDic;
        #endregion

        #region 构造函数
        public FiniteStateMachine()
        {
            _fsmDic = new Dictionary<Type, FiniteState>();
        }
        #endregion

        #region 方法
        /// <summary>
        /// 添加状态
        /// </summary>
        /// <param name="key">标识符</param>
        /// <param name="state">状态</param>
        public void AddState(Type key, FiniteState state)
        {
            if (!_fsmDic.ContainsKey(key)) _fsmDic.Add(key, state);
            else Debug.LogWarningFormat("Key:{0} Value:{1} FSM状态重复添加", key.ToString(), state);
        }

        /// <summary>
        /// 删除状态
        /// </summary>
        /// <param name="key">标识符</param>
        /// <param name="state">状态</param>
        public void RemoveState(Type key, FiniteState state)
        {
            if (_fsmDic.ContainsKey(key))
            {
                if (CurrentState == key) Debug.LogWarningFormat("Key:{0} Value:{1} FSM状态正在运行无法删除", key.ToString(), state);
                else _fsmDic.Remove(key);
            }
            else Debug.LogWarningFormat("Key:{0} Value:{1} FSM状态不存在无法删除", key.ToString(), state);
        }

        /// <summary>
        /// 转换状态
        /// </summary>
        /// <param name="key">标识符</param>
        void TransitionState(Type key)
        {
            if (enable)
            {
                if (_fsmDic.ContainsKey(key))
                {
                    if (CurrentState != key)
                    {
                        _fsmDic[CurrentState].OnExit();
                        CurrentState = key;
                        _fsmDic[CurrentState].OnEnter();
                    }
                    else Debug.LogWarningFormat("Key:{0} FSM状态机已在当前状态无需转换", key.ToString());
                }
                else Debug.LogWarningFormat("Key:{0} FSM状态不存在无法转换", key.ToString());
            }
            else Debug.LogWarningFormat("Key:{0} FSM状态机未启动无法转换状态", key.ToString());
        }

        /// <summary>
        /// 启动状态机
        /// </summary>
        /// <param name="key">标识符</param>
        public void StartFSM(Type key)
        {
            if (!enable)
            {
                enable = true;
                CurrentState = key;
                _fsmDic[CurrentState].OnEnter();
            }
            else Debug.LogWarningFormat("FSM 状态机已启动无需重复开启");
        }

        /// <summary>
        /// 保持状态机
        /// </summary>
        public void StayFSM()
        {
            if (enable)
            {
                if (CurrentState != null)
                {
                    if (_fsmDic[CurrentState].TransitionState() != null) TransitionState(_fsmDic[CurrentState].TransitionState());
                    else _fsmDic[CurrentState].OnUpdate();
                }
                else Debug.LogWarningFormat("FSM 状态机没有当前状态 无法保持");
            }
            else Debug.LogWarningFormat("FSM 状态机已停止 无需保持");
        }

        /// <summary>
        /// 停止状态机
        /// </summary>
        public void StopFSM()
        {
            if (enable)
            {
                enable = false;
                _fsmDic[CurrentState].OnExit();
            }
            else Debug.LogWarningFormat("FSM 状态状态机已停止 无需重复操作");
        }
        #endregion
    }
}